
#include <scott/SVector.h>

BOOST_AUTO_TEST_SUITE( SVector_Test_Suite )

BOOST_AUTO_TEST_CASE( SVectorTypeDescriptor_SimpleType_Test )
{
	//SVectorTypeDescriptorSp vtd = 
	//	SVectorTypeDescriptor::Create("plugin", "vnumber", "Vector of SNumber", STypeNumber);

	//SVectorSp v = SVector::Create(vtd);
	//v->AddItem( SNumber::Create(1) );
	//v->AddItem( SNumber::Create(2) );
	//v->AddItem( SNumber::Create(3) );

	//SValueSp v0 = v->Get(0);
	//SNumberSp v1 = v->Get<SNumber>(1);

	SVectorTypeDescriptorSp vtd = SVectorTypeDescriptor::Create("plugin", "SimpleVector", "A simple vector", STypeNumber);

	BOOST_CHECK( vtd->GetName() == "SimpleVector" );
	BOOST_CHECK( vtd->GetDescription() == "A simple vector" );
	BOOST_CHECK( vtd->IsValid() == true );
	BOOST_CHECK( vtd->GetItemType() == STypeNumber );
	BOOST_CHECK( vtd->GetFullyQualifiedItemTypeName() == "SNumber" );
	BOOST_CHECK( vtd->Describe(STypeVector) == true);
	BOOST_CHECK( vtd->GetDescribedType() == STypeVector );		
}

BOOST_AUTO_TEST_CASE( SVectorTypeDescriptor_ComplexType_Test )
{
	// Data
	SEnumTypeDescriptorSp etd = SEnumTypeDescriptor::Create("plugin", "colors", "");
	etd->AddEntry("red", 0, "red color");			
	etd->AddEntry("yellow", 1, "yellow color");
	etd->AddEntry("green", 2, "green color");

	// Test
	SVectorTypeDescriptorSp vtd = SVectorTypeDescriptor::Create("plugin", "ComplexVector", "A complex vector", etd);

	BOOST_CHECK( vtd->GetName() == "ComplexVector" );
	BOOST_CHECK( vtd->GetDescription() == "A complex vector" );
	BOOST_CHECK( vtd->IsValid() == true );
	BOOST_CHECK( vtd->GetItemType() == STypeEnum );
	BOOST_CHECK( vtd->GetItemTypeDescriptor() == etd );
	BOOST_CHECK( vtd->GetFullyQualifiedItemTypeName() == "plugin.colors" );
	BOOST_CHECK( vtd->Describe(STypeVector) == true);
	BOOST_CHECK( vtd->GetDescribedType() == STypeVector );		
}

BOOST_AUTO_TEST_CASE( SVector_SimpleType_Add_Test )
{
	SVectorTypeDescriptorSp vtd = SVectorTypeDescriptor::Create("plugin", "SimpleVector", "A simple vector", STypeString);

	SVectorSp v = SVector::Create(vtd);

	BOOST_CHECK( v->GetType() == STypeVector );
	BOOST_CHECK( v->GetLength() == 0 );
	BOOST_CHECK( v->GetTypeDescriptor() == vtd );
	BOOST_CHECK_THROW( v->Get(0), SArgumentException );
	BOOST_CHECK( v->ToString() == "{}" );

	BOOST_CHECK_THROW( v->AddItem( SByte::Create(10) ), SArgumentException );
	BOOST_CHECK_THROW( v->AddItem( SChar::Create('C') ), SArgumentException );

	v->AddItem( SString::Create("One") );
	v->AddItem( SString::Create("Two") );
	v->AddItem( SString::Create("Three") );

	BOOST_CHECK( v->GetLength() == 3 );
	BOOST_CHECK( v->Get<SString>(0)->Get() == "One" );
	BOOST_CHECK( v->Get<SString>(1)->Get() == "Two" );
	BOOST_CHECK( v->Get<SString>(2)->Get() == "Three" );
	BOOST_CHECK_THROW( v->Get(3), SArgumentException );
	BOOST_CHECK( v->ToString() == "{ \"One\", \"Two\", \"Three\" }" );
}

BOOST_AUTO_TEST_CASE( SVector_SimpleType_Parse_Test )
{
	SVectorTypeDescriptorSp vtd = SVectorTypeDescriptor::Create("plugin", "SimpleVector", "A simple vector", STypeString);

	// Vector with three elements
	SVectorSp v = SVector::Parse(vtd, "{   \"One\" ,  \"Two\",   \"Three\"   }");

	BOOST_CHECK( v->GetLength() == 3 );
	BOOST_CHECK( v->Get<SString>(0)->Get() == "One" );
	BOOST_CHECK( v->Get<SString>(1)->Get() == "Two" );
	BOOST_CHECK( v->Get<SString>(2)->Get() == "Three" );
	BOOST_CHECK_THROW( v->Get(3), SArgumentException );
	BOOST_CHECK( v->ToString() == "{ \"One\", \"Two\", \"Three\" }" );
	BOOST_CHECK_THROW( v->ToString("x"), SArgumentException );

	// Empty vector
	v = SVector::Parse(vtd, "{  }");

	BOOST_CHECK( v->GetLength() == 0 );
	BOOST_CHECK( v->ToString() == "{}" );

	// Vector with only one element
	v = SVector::Parse(vtd, "{ \"One\"  }");

	BOOST_CHECK( v->GetLength() == 1 );
	BOOST_CHECK( v->Get<SString>(0)->Get() == "One" );
	BOOST_CHECK( v->ToString() == "{ \"One\" }" );
}

BOOST_AUTO_TEST_CASE( SVector_Byte_Parse_Test )
{
	SVectorTypeDescriptorSp vtd = SVectorTypeDescriptor::Create("plugin", "Buffer", "This is a buffer", STypeByte);

	// A byte vector with an even number of exadecimal digits
	SVectorSp v = SVector::Parse(vtd, "0x0001020304FFFEFDFCFB");

	BOOST_CHECK( v->GetLength() == 10 );
	BOOST_CHECK( v->Get<SByte>(0)->Get() == 0 );
	BOOST_CHECK( v->Get<SByte>(1)->Get() == 1 );
	BOOST_CHECK( v->Get<SByte>(2)->Get() == 2 );
	BOOST_CHECK( v->Get<SByte>(3)->Get() == 3 );
	BOOST_CHECK( v->Get<SByte>(4)->Get() == 4 );
	BOOST_CHECK( v->Get<SByte>(5)->Get() == 255 );
	BOOST_CHECK( v->Get<SByte>(6)->Get() == 254 );
	BOOST_CHECK( v->Get<SByte>(7)->Get() == 253 );
	BOOST_CHECK( v->Get<SByte>(8)->Get() == 252 );
	BOOST_CHECK( v->Get<SByte>(9)->Get() == 251 );
	BOOST_CHECK( v->ToString() == "{ 0, 1, 2, 3, 4, 255, 254, 253, 252, 251 }" );
	BOOST_CHECK( v->ToString("x") == "0x0001020304FFFEFDFCFB" );
	BOOST_CHECK( v->ToString("nx") == "0001020304FFFEFDFCFB" );
	BOOST_CHECK( v->ToString("1nx") == "00" );
	BOOST_CHECK( v->ToString("2nx") == "0001" );
	BOOST_CHECK( v->ToString("3nx") == "000102" );
	BOOST_CHECK( v->ToString("4nx") == "00010203" );

	// A byte vector with an odd number of exadecimal digits
	v = SVector::Parse(vtd, "0xABC");

	BOOST_CHECK( v->ToString() == "{ 171, 12 }" );
	BOOST_CHECK( v->ToString("x") == "0xAB0C" );

	v = SVector::Parse(vtd, "{}");

	// A byte vector with zero items
	BOOST_CHECK( v->ToString() == "{}" );
	BOOST_CHECK( v->ToString("x") == "{}" );
}

BOOST_AUTO_TEST_CASE( SVector_ComplexType_Parse_Test )
{
	// Data
	SEnumTypeDescriptorSp etd = SEnumTypeDescriptor::Create("plugin", "colors", "");
	etd->AddEntry("red", 0, "red color");			
	etd->AddEntry("yellow", 1, "yellow color");
	etd->AddEntry("green", 2, "green color");

	// Test
	SVectorTypeDescriptorSp vtd = SVectorTypeDescriptor::Create("plugin", "ComplexVector", "A complex vector", etd);

	// Vector with three elements
	SVectorSp v = SVector::Parse(vtd, "{   red ,  yellow,   green }");

	BOOST_CHECK( v->GetLength() == 3 );
	BOOST_CHECK( v->Get<SEnum>(0)->Get() == "red" );
	BOOST_CHECK( v->Get<SEnum>(1)->Get() == "yellow" );
	BOOST_CHECK( v->Get<SEnum>(2)->Get() == "green" );
	BOOST_CHECK_THROW( v->Get(3), SArgumentException );
	BOOST_CHECK( v->ToString() == "{ red, yellow, green }" );

	// Empty vector
	v = SVector::Parse(vtd, "{}");

	BOOST_CHECK( v->GetLength() == 0 );
	BOOST_CHECK( v->ToString() == "{}" );

	// Vector with only one element
	v = SVector::Parse(vtd, "{ red  }");

	BOOST_CHECK( v->GetLength() == 1 );
	BOOST_CHECK( v->Get<SEnum>(0)->Get() == "red" );
	BOOST_CHECK( v->ToString() == "{ red }" );
}


BOOST_AUTO_TEST_SUITE_END()
